package org.activequant.tradesystem.ib;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activequant.core.domainmodel.InstrumentSpecification;
import org.activequant.core.domainmodel.marketscanner.ScanCriteria;
import org.activequant.tradesystem.ib.selectorstrategy.CrossReferencingSelectorStrategy;
import org.activequant.tradesystem.ib.selectorstrategy.ISelectorStrategy;
import org.activequant.tradesystem.ib.selectorstrategy.TopScannersSelector;

import com.ib.algokit.TraderProxy;
/**
 * supports up to 10 scanners simultaneously
 * Holds hardcoded ScannerCriteria definitions.
 * Holds the following associated variables:
 * <ul>
 * <li>marketScannerFactory(MarketScannerFactory)</li>
 * <li>ema(TraderProxy)</li>
 * <li>scanCriterias(List&lt;ScanCriteria&gt;)</li>
 * </ul>
 * @author Dimitar
 *
 */
public class MarketScanHelper{
	/**
	 * private MarketScannerFactory marketScannerFactory;
	 */
	private MarketScannerFactory marketScannerFactory;
	/**
	 * private final TraderProxy ema;
	 */
	private final TraderProxy ema;	
	/**
	 * private List&lt;ScanCriteria&gt; scanCriterias=new ArrayList&lt;ScanCriteria&gt;();<br/>
	 * what scanCriterias do we want to try and activate? (some won't respond - inactive)
	 */
	private List<ScanCriteria> scanCriterias=new ArrayList<ScanCriteria>();
	
	//private List<ScanCriteria> selectedScanCriterias=new ArrayList<ScanCriteria>();
	/**
	 * Map&lt;InstrumentSpecification,InstrumentStats&gt; possibleCandidates= new HashMap&lt;InstrumentSpecification,InstrumentStats&gt;();
	 */
	Map<InstrumentSpecification,InstrumentStats> possibleCandidates= new HashMap<InstrumentSpecification,InstrumentStats>();
	/**
	 * TopScannersSelector topScannersSelector=new TopScannersSelector();
	 */
	TopScannersSelector topScannersSelector=new TopScannersSelector();
	/**
	 * private ISelectorStrategy[] strategies={new CrossReferencingSelectorStrategy(),topScannersSelector};
	 */
	private ISelectorStrategy[] strategies={new CrossReferencingSelectorStrategy(),topScannersSelector};
	
	public void scan() {
		//scanCriteriaDao.deleteAll();
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_OPT_VOLUME_PUT_CALL_RATIO_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPT_VOLUME_PUT_CALL_RATIO_Criteria());//this means a bullish underlying (investors think it will go up soon)
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_VS_13W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_VS_13W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_VS_26W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_VS_26W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_VS_52W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_VS_52W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_OPT_IMP_VOLAT_OVER_HIST_Criteria());//different market ahead.
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPT_IMP_VOLAT_OVER_HIST_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_OPT_IMP_VOLAT_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPT_IMP_VOLAT_GAIN_Criteria());//The options markets believe will have the greatest up or down price movement in the future as compared to the past.
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPT_IMP_VOLAT_LOSE_Criteria());//The options markets believe these symbols had a large up and down price movement and will stabilize in the future.
		scanCriterias.add(ScanCriteriaFactory.getInstance().getOPT_VOLUME_MOST_ACTIVE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_OPT_VOLUME_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_OPT_OPEN_INTEREST_PUT_CALL_RATIO_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPT_OPEN_INTEREST_PUT_CALL_RATIO_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_PERC_GAIN_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getMOST_ACTIVE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_PERC_LOSE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_VOLUME_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_PRICE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_TRADE_COUNT_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_TRADE_RATE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_PRICE_RANGE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_PRICE_RANGE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_VOLUME_RATE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPT_IMP_VOLAT_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getOPT_OPEN_INTEREST_MOST_ACTIVE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getNOT_OPEN_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHALTED_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPEN_PERC_GAIN_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPEN_PERC_LOSE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_OPEN_GAP_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPEN_GAP_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_SYNTH_BID_REV_NAT_YIELD_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_SYNTH_BID_REV_NAT_YIELD_Criteria());		
		for(ScanCriteria criteria:scanCriterias){
			ema.getScanCriteriaDao().update(criteria);
		}
		for(ScanCriteria criteria:scanCriterias){
			marketScannerFactory.getScanner(criteria);
		}
	}
	
	public void getOpportunities(){
		for(ISelectorStrategy strategy:strategies){
			strategy.getOpportunities(marketScannerFactory, possibleCandidates);
		}
		marketScannerFactory.resetMarketScanSubscriptions();
		//System.out.println("possibleCandidates "+possibleCandidates.size());	
		//System.out.println("topScannersSelector.getSelectedScanCriterias() "+topScannersSelector.getSelectedScanCriterias().size());
		for(ScanCriteria criteria:topScannersSelector.getSelectedScanCriterias()){
			marketScannerFactory.getScanner(criteria,true);
		}
	}
	/**
	 * Initializes some fixed ScanCriteria(s) into the associated scanCriterias(List&lt;ScanCriteria&gt;) and saves/updates them
	 */
	public void initScanCriterias(){
		scanCriterias.clear();
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_PERC_GAIN_Criteria());
//		scanCriterias.add(ScanCriteriaFactory.getInstance().getOPT_VOLUME_MOST_ACTIVE_Criteria());//this means a bullish underlying (investors think it will go up soon)
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHIGH_VS_13W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_VS_13W_HL_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getMOST_ACTIVE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_PERC_LOSE_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_VOLUME_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getHOT_BY_PRICE_Criteria());
//		scanCriterias.add(ScanCriteriaFactory.getInstance().getLOW_OPT_VOLUME_PUT_CALL_RATIO_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPEN_PERC_GAIN_Criteria());
		scanCriterias.add(ScanCriteriaFactory.getInstance().getTOP_OPEN_PERC_LOSE_Criteria());
		for(ScanCriteria criteria:scanCriterias){
			ema.getScanCriteriaDao().update(criteria);
		}
	}
	
	/**
	 * Iterates the associated scanCriterias(List&lt;ScanCriteria&gt;) and activates a permanent MarketScanner worker for each of them
	 */
	public void getFixedScanners(){
		for(final ScanCriteria criteria:scanCriterias){
			new Thread(new Runnable() {
				public void run() {
					marketScannerFactory.getScanner(criteria,true);
				}
			}).start();
			
		}
		//System.out.println("possibleCandidates "+possibleCandidates.size());	
		//System.out.println("topScannersSelector.getSelectedScanCriterias() "+topScannersSelector.getSelectedScanCriterias().size());
	}	
	/**
	 * Constructs a MarketScanHelper and its marketScannerFactory(MarketScannerFactory).
	 * It also initializes some fixed ScanCriteria(s) into the associated scanCriterias(List&lt;ScanCriteria&gt;) 
	 * @param ema
	 */
	public MarketScanHelper(TraderProxy ema) {
		this.ema=ema;
		this.marketScannerFactory=new MarketScannerFactory(ema);
		initScanCriterias();
	}
	/**
	 * the associated scanCriterias(List&lt;ScanCriteria&gt;)
	 * @return
	 */
	public List<ScanCriteria> getScanCriterias() {
		return scanCriterias;
	}
		
}
